package com.qixin.activiti.api;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qixin.appPush.AppPush;
import com.qixin.modules.ea.entity.*;
import com.qixin.modules.ea.mapper.*;
import com.qixin.modules.eaApplication.entity.*;
import com.qixin.modules.eaApplication.mapper.*;
import com.qixin.modules.eaBasic.entity.EaTask;
import com.qixin.modules.eaBasic.mapper.EaTaskMapper;
import com.qixin.modules.eaBasic.vo.IdVo;
import com.qixin.modules.eaLoan.entity.EaLoanbill;
import com.qixin.modules.eaLoan.entity.EaRepaymentbill;
import com.qixin.modules.eaLoan.mapper.EaLoanbillMapper;
import com.qixin.modules.eaLoan.mapper.EaRepaymentbillMapper;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.EmptyUtil;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.common.util.Uuid32Util;
import org.jeecg.modules.activiti.entity.ActBusiness;
import org.jeecg.modules.activiti.entity.ActivitiConstant;
import org.jeecg.modules.activiti.entity.ProcessNodeVo;
import org.jeecg.modules.activiti.mapper.ActEaTaskMapper;
import org.jeecg.modules.activiti.service.Impl.ActBusinessServiceImpl;
import org.jeecg.modules.activiti.service.Impl.ActZprocessServiceImpl;
import org.jeecg.modules.system.vo.ActivitiCancelVo;
import org.jeecg.modules.system.vo.ActivitiVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author:wly
 * @Date:2021/10/18
 * @Describtion: 工作流实现类
 */
@Service
public class ActivitiServiceImpl implements IActivitiService {
    @Autowired
    private ActBusinessServiceImpl actBusinessService;
    @Autowired
    ActZprocessServiceImpl actZprocessService;
    @Autowired
    EaSysDictItemMapper eaSysDictItemMapper;
    @Autowired
    EaTaskMapper eaTaskMapper;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    ISysBaseAPI sysBaseAPI;
    @Autowired
    EaBusinessApplyMapper eaBusinessApplyMapper;
    @Autowired
    EaBusinessApplyChangeMapper eaBusinessApplyChangeMapper;
    @Autowired
    EaEntertainApplyMapper eaEntertainApplyMapper;
    @Autowired
    EaEntertainChangeMapper eaEntertainChangeMapper;
    @Autowired
    EaTravelMapper eaTravelMapper;
    @Autowired
    EaEntertainMapper eaEntertainMapper;
    @Autowired
    EaPaymentMapper eaPaymentMapper;
    @Autowired
    EaLoanbillMapper eaLoanbillMapper;
    @Autowired
    EaRepaymentbillMapper eaRepaymentbillMapper;
    @Autowired
    private EaHostObjectMapper eaHostObjectMapper;
    @Autowired
    private AppPush appPush;
    @Autowired
    private EaEntertainReceptionActivityMapper eaEntertainReceptionActivityMapper;
    @Autowired
    private ActEaTaskMapper actEaTaskMapper;
    @Autowired
    EaCommunicationsMapper eaCommunicationsMapper;
    @Autowired
    EaPhoneRecordMapper eaPhoneRecordMapper;
    @Autowired
    private EaBusinessPerDtlMapper eaBusinessPerDtlMapper;

    /**
     *
     * @param
     */
    @Override
    @Transactional
    public void addActivitiApply(ActivitiVo activitiVo,Boolean firstGateway) {
        //不同的单据类型,匹配不同的流程实例
        String dictItemId = pickActivitiByFormType(activitiVo.getType());

        //eaTask,单据涉及到的表名(如差旅费报销单ea_travel)
        Map<String,Object> taskParams = new HashMap<String,Object>();
        taskParams.put("form_id",activitiVo.getId());
        List<EaTask> eaTaskList  = eaTaskMapper.selectByMap(taskParams);
        EaTask eaTask = new EaTask();
        if(eaTaskList.size() > 0){
            eaTask = eaTaskList.get(0);
        }
        String tableName = "";
        //通过type判断
        tableName = changeTypeToTableName(activitiVo.getType());

        /*添加申请草稿状态*/
        ActBusiness actBusiness = new ActBusiness();
        //新增数据 保存至我的申请业务
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String username = sysUser.getId();
        actBusiness.setId(UUIDGenerator.generate());
        actBusiness.setUserId(username);        //
        actBusiness.setTableId(eaTask.getFormId());        //单据id
        actBusiness.setStatus(ActivitiConstant.STATUS_DEALING);   //处理中状态
        actBusiness.setResult(ActivitiConstant.RESULT_DEALING);   //处理中结果
        actBusiness.setFirstGateway(firstGateway);                //第一节点是否为网关

        //获取数据字典,报销流程id
        EaSysDictItem eaSysDictItem = eaSysDictItemMapper.selectById(dictItemId);
        String itemValue = eaSysDictItem.getItemValue();    //流程id
        actBusiness.setProcDefId(itemValue);

        actBusiness.setSendMessage(true);  //发送站内消息
        actBusiness.setTitle(eaTask.getTitle());     //标题
        actBusiness.setTableName(tableName);
        actBusinessService.save(actBusiness);

        //获取第一个节点
        ProcessNodeVo node = actZprocessService.getFirstNode(itemValue,tableName,eaTask.getFormId());
        String assignees = "";   //执行人
        if(node.getUsers() != null && node.getUsers().size() > 0){
            for (int i = 0; i < node.getUsers().size(); i++) {
                if(assignees.equals("")){
                    assignees = EmptyUtil.checkNull(node.getUsers().get(i).getId());
                }else{
                    assignees = assignees + "," + EmptyUtil.checkNull(node.getUsers().get(i).getId());
                }
            }
        }
        actBusiness.setAssignees(assignees);

        /*提交申请 启动流程*/
        Map<String, Object> busiData = actBusinessService.getBusiData(eaTask.getFormId(), tableName);

        if (MapUtil.isNotEmpty(busiData)&&busiData.get(ActivitiConstant.titleKey)!=null){
            //如果表单里有 标题  更新一下
            actBusiness.setTitle(busiData.get(ActivitiConstant.titleKey)+"");
        }

        Map<String,Object> processMap = actZprocessService.startProcess(actBusiness,activitiVo.getType());
        String processInstanceId = EmptyUtil.checkNull(processMap.get("piId"));
        String workflowTaskId = EmptyUtil.checkNull(processMap.get("workflowTaskId"));
        actBusiness.setProcInstId(processInstanceId);
        actBusiness.setStatus(ActivitiConstant.STATUS_DEALING);
        actBusiness.setResult(ActivitiConstant.RESULT_DEALING);
        actBusiness.setApplyTime(new Date());

        //设置审核通过状态
        taskService.setVariable(workflowTaskId,"audit","1");

        eaTask.setWorkflowTaskId(workflowTaskId);    //工作流任务id
        eaTask.setProcinstId(processInstanceId);     //流程id
        eaTask.setStatus("0");
        eaTaskMapper.updateById(eaTask);

        actBusinessService.updateById(actBusiness);
        //修改业务表的流程字段
        actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"0");
    }

    //根据不同的单据类型,获取不同的字典
    private String pickActivitiByFormType(String type) {
        if(type.equals("4")){  //出差申请单
            return "1451493617144766465";
        }else if(type.equals("5")){//出差申请变更单
            return "1450032319529865217";
        }else if(type.equals("6")){//招待费申请单
            return "1451490342672605185";
        }else if(type.equals("7")){//招待费申请变更单
            return "1451490396074483713";
        }else if(type.equals("8")){//招待费报销单
            return "1451490465523769345";
        }else if(type.equals("9")){//资金支付审批单
            return "1451490499501826049";
        }else if(type.equals("1")){//差旅费报销单
            return "1451080760615854082";
        }else if(type.equals("2")){//借款单
            return "1451490532590690306";
        }else if(type.equals("3")){//还款单
            return "1451092237255008257";
        }else if(type.equals("10")){//通讯费报销单
            return "1455798810548199426";
        }else{//电话记录单
            return "1455798880240754689";
        }
    }

    /**
     *
     * @param
     */
    @Override
    @Transactional
    public void sendActivitiApply(ActivitiVo activitiVo,Boolean firstGateway) {
        //不同的单据类型,匹配不同的流程实例
        String dictItemId = pickActivitiByFormType(activitiVo.getType());

        //eaTask,单据涉及到的表名(如差旅费报销单ea_travel)
        Map<String,Object> taskParams = new HashMap<String,Object>();
        taskParams.put("form_id",activitiVo.getId());
        List<EaTask> eaTaskList  = eaTaskMapper.selectByMap(taskParams);
        EaTask eaTask = new EaTask();
        if(eaTaskList.size() > 0){
            eaTask = eaTaskList.get(0);
        }
        String tableName = "";
        //通过type判断
        tableName = changeTypeToTableName(activitiVo.getType());

        /*添加申请草稿状态*/
        ActBusiness actBusiness = new ActBusiness();
        //新增数据 保存至我的申请业务
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String username = sysUser.getId();
        actBusiness.setId(UUIDGenerator.generate());
        actBusiness.setUserId(username);        //
        actBusiness.setTableId(eaTask.getFormId());        //单据id
        actBusiness.setStatus(ActivitiConstant.STATUS_DEALING);   //处理中状态
        actBusiness.setResult(ActivitiConstant.RESULT_DEALING);   //处理中结果
        actBusiness.setFirstGateway(firstGateway);                //第一节点是否为网关

        //获取数据字典,报销流程id
        EaSysDictItem eaSysDictItem = eaSysDictItemMapper.selectById(dictItemId);
        String itemValue = eaSysDictItem.getItemValue();    //流程id
        actBusiness.setProcDefId(itemValue);

        actBusiness.setSendMessage(true);  //发送站内消息
        actBusiness.setTitle(eaTask.getTitle());     //标题
        actBusiness.setTableName(tableName);
        actBusinessService.save(actBusiness);

        //获取第一个节点
        ProcessNodeVo node = actZprocessService.getFirstNode(itemValue,tableName,eaTask.getFormId());
        String assignees = "";   //执行人
        if(node.getUsers() != null && node.getUsers().size() > 0){
            for (int i = 0; i < node.getUsers().size(); i++) {
                if(assignees.equals("")){
                    assignees = EmptyUtil.checkNull(node.getUsers().get(i).getId());
                }else{
                    assignees = assignees + "," + EmptyUtil.checkNull(node.getUsers().get(i).getId());
                }
            }
        }
        actBusiness.setAssignees(assignees);

        /*提交申请 启动流程*/
        Map<String, Object> busiData = actBusinessService.getBusiData(eaTask.getFormId(), tableName);

        if (MapUtil.isNotEmpty(busiData)&&busiData.get(ActivitiConstant.titleKey)!=null){
            //如果表单里有 标题  更新一下
            actBusiness.setTitle(busiData.get(ActivitiConstant.titleKey)+"");
        }

        Map<String,Object> processMap = actZprocessService.startProcess(actBusiness,activitiVo.getType());

        String processInstanceId = EmptyUtil.checkNull(processMap.get("piId"));
        String workflowTaskId = EmptyUtil.checkNull(processMap.get("workflowTaskId"));
        actBusiness.setProcInstId(processInstanceId);
        actBusiness.setStatus(ActivitiConstant.STATUS_DEALING);
        actBusiness.setResult(ActivitiConstant.RESULT_DEALING);
        actBusiness.setApplyTime(new Date());

        //设置审核通过状态
        taskService.setVariable(workflowTaskId,"audit","1");

        eaTask.setWorkflowTaskId(workflowTaskId);    //工作流任务id
        eaTask.setProcinstId(processInstanceId);     //流程id
        eaTask.setStatus("0");
        eaTaskMapper.updateById(eaTask);

        actBusinessService.updateById(actBusiness);
        //修改业务表的流程字段
        actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"0");

        //提交到第二个节点
        updateWrokflowByTaskId(eaTask);
    }

    //通过type类型获取数据库表名
    private String changeTypeToTableName(String type) {
        String tableName = "";
        switch (type){
            case "1":
                tableName = "ea_travel";
                break;
            case "2":
                tableName = "ea_loanbill";
                break;
            case "3":
                tableName = "ea_repaymentbill";
                break;
            case "4":
                tableName = "ea_business_apply";
                break;
            case "5":
                tableName = "ea_business_apply_change";
                break;
            case "6":
                tableName = "ea_entertain_apply";
                break;
            case "7":
                tableName = "ea_entertain_change";
                break;
            case "8":
                tableName = "ea_entertain";
                break;
            case "9":
                tableName = "ea_payment";
                break;
            case "10":
                tableName = "ea_communications";
                break;
            case "11":
                tableName = "ea_phone_record";
                break;
        }
        return tableName;
    }



    @Transactional
    public String updateWrokflowByTaskId(ActivitiVo activitiVo,String auditType) {
        //eaTask,单据涉及到的表名(如差旅费报销单ea_travel)
        Map<String,Object> taskParams = new HashMap<String,Object>();
        taskParams.put("form_id",activitiVo.getId());
        List<EaTask> eaTaskList  = eaTaskMapper.selectByMap(taskParams);
        EaTask eaTask = new EaTask();
        if(eaTaskList.size() > 0){
            eaTask = eaTaskList.get(0);
        }

        String ids = eaTask.getWorkflowTaskId();     //工作流任务id
        String procInstId = eaTask.getProcinstId();     //流程id
        String assignees = "";    //下个节点审核人
        String comment = EmptyUtil.checkNull(activitiVo.getAuditComment());
        if(ids.contains(",")){
            String[] id = ids.split(",");

            for (int i = 0; i < id.length; i++) {
                taskService.addComment(id[i], procInstId, comment);
                ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
                Task task = taskService.createTaskQuery().taskId(id[i]).singleResult();
                if(StrUtil.isNotBlank(task.getOwner())&&!("RESOLVED").equals(task.getDelegationState().toString())){
                    // 未解决的委托任务 先resolve
                    String oldAssignee = task.getAssignee();
                    taskService.resolveTask(id[i]);
                    taskService.setAssignee(id[i], oldAssignee);
                }

                /**
                 * 修改流程表单变量
                 * 表单参数
                 */
                LambdaQueryWrapper<ActBusiness> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ActBusiness::getProcInstId,pi.getProcessInstanceId());
                ActBusiness one = actBusinessService.getOne(queryWrapper);
                Map<String, Object> busiData = actBusinessService.getBusiData(one.getTableId(), one.getTableName());

                /**
                 * 获取所有流程变量 并修改
                 */
                for(String key : busiData.keySet()){
                    taskService.setVariable(id[i],key,busiData.get(key));
                }

        /*会签思路：
        act_hi_identitylink记录着审批历史 ActivitiConstant.EXECUTOR_TYPE_p 标识审批通过
        1、节点设置中增加人数字段，表示需要多少人通过这个任务节点才通过
        2、此处查询审批历史，查看当前节点的审批情况，符合预设的人数调用 taskService.complete(id); 完成该节点任务
        否则只记录审批数据，不完成该任务节点
        3、会有的问题：
            1、如此，审批过的人代办中还会看到这条任务，需要标识自己审批过，但是这条任务自己不能再审了  或 能再审，但是再审记得把之前审批过的记录删掉
            2、下一个节点的审批人只能最后通过的人选择才有效
            3、如果下一个节点是会签，指定下一节点的审批人的数量必须不小于节点预设数量
            其他问题，待暴露
          */
                /*完成任务*/
                try {
                    taskService.complete(id[i]);
                }catch (Exception e){
                    throw new RuntimeException("流转条件不满足,请检查");
                }
                if(auditType.equals("back")){
                    //驳回时,将流程历史中的delete_reason改成backed
                    actZprocessService.updateTaskBack(id[i]);
                }
                if(auditType.equals("cancel")){
                    //驳回时,将流程历史中的delete_reason改成cancel
                    actZprocessService.updateTaskCancel(id[i]);
                }
                ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey());
                //修改业务表的流程字段
                String actStatus = "1";
                if(auditType.equals("back")){
                    actStatus = "3";
                }
                actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),actStatus);
                eaTask.setStatus(actStatus);

                task.getName();
                LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
                // 判断下一个节点
                if(tasks!=null&&tasks.size()>0){
                    for(Task t : tasks){
                        if(StrUtil.isBlank(assignees)){
                            // 如果下个节点未分配审批人为空 取消结束流程
                            List<LoginUser> users = actZprocessService.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId()).getUsers();
                            if(users==null||users.size()==0){
                                /*runtimeService.deleteProcessInstance(procInstId, "canceled-审批节点未分配审批人，流程自动中断取消");
                                actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED);
                                actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT);
                                actBusinessService.updateById(actBusiness);
                                //修改业务表的流程字段
                                actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"0");
                                eaTask.setStatus("0");

                                break;*/
                                throw new RuntimeException("下级节点未分配审批人，请设置");

                            }else{
                                // 避免重复添加
                                List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                                if(list==null||list.size()==0) {
                                    // 分配了节点负责人分发给全部
                                    for (LoginUser user : users) {
                                        taskService.addCandidateUser(t.getId(), user.getId());
                                        // 异步发消息
                                        actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);

                                        if(auditType.equals("back")){
                                            appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","3");
                                        }else if(auditType.equals("cancel")) {

                                        }else{
                                            appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                        }
                                    }
                                    taskService.setPriority(t.getId(), task.getPriority());
                                }
                            }
                        }else{
                            // 避免重复添加
                            List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                            if(list==null||list.size()==0) {

                                for(String assignee : assignees.split(",")){
                                    taskService.addCandidateUser(t.getId(), assignee);
                                    // 异步发消息
                                    LoginUser user = sysBaseAPI.getUserById(assignee);
                                    actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);
                                    taskService.setPriority(t.getId(), 0);

                                    if(auditType.equals("back")){
                                        appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","3");
                                    }else if(auditType.equals("cancel")) {

                                    }else{
                                        appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                    }
                                }
                            }
                        }
                    }
                } else {
                    actBusiness.setStatus(ActivitiConstant.STATUS_FINISH);
                    actBusiness.setResult(ActivitiConstant.RESULT_PASS);
                    actBusinessService.updateById(actBusiness);
                    // 异步发消息
                    LoginUser user = sysBaseAPI.getUserById(actBusiness.getUserId());
                    actZprocessService.sendMessage(actBusiness.getId(),loginUser,user,ActivitiConstant.MESSAGE_PASS_CONTENT,
                            String.format("您的 【%s】 申请已通过！",actBusiness.getTitle()),true, false, false);
                    //修改业务表的流程字段
                    actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"2");
                    eaTask.setStatus("2");

                    //判断是否变更单,变更单审核通过完结时,需要将变更单的信息更新到申请单
                    updateApplyByAuditChange(actBusiness.getTableName(),actBusiness.getTableId());

                    appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "审核已通过","已审核",eaTask.getFormId(),eaTask.getFormType(),"2","2");
                }
                // 记录实际审批人员
                if(auditType.equals("pass")){
                    actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                            ActivitiConstant.EXECUTOR_TYPE_p, loginUser.getId(), id[i], procInstId);
                }else{
                    actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                            ActivitiConstant.EXECUTOR_TYPE_b, loginUser.getId(), id[i], procInstId);
                }

                //更新任务
                String workflowTaskId = "";
                for (int j = 0; j < tasks.size(); j++) {
                    if(workflowTaskId.equals("")){
                        workflowTaskId = tasks.get(j).getId();
                    }else{
                        workflowTaskId = workflowTaskId + "," + tasks.get(j).getId();
                    }
                }
                eaTask.setWorkflowTaskId(workflowTaskId);
                eaTaskMapper.updateById(eaTask);
            }
            return "";
        }else{
            taskService.addComment(ids, procInstId, comment);
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
            Task task = taskService.createTaskQuery().taskId(ids).singleResult();
            if(StrUtil.isNotBlank(task.getOwner())&&!("RESOLVED").equals(task.getDelegationState().toString())){
                // 未解决的委托任务 先resolve
                String oldAssignee = task.getAssignee();
                taskService.resolveTask(ids);
                taskService.setAssignee(ids, oldAssignee);
            }

            /**
             * 修改流程表单变量
             * 表单参数
             */
            LambdaQueryWrapper<ActBusiness> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ActBusiness::getProcInstId,pi.getProcessInstanceId());
            ActBusiness one = actBusinessService.getOne(queryWrapper);
            Map<String, Object> busiData = actBusinessService.getBusiData(one.getTableId(), one.getTableName());

            /**
             * 获取所有流程变量 并修改
             */
            for(String key : busiData.keySet()){
                taskService.setVariable(ids,key,busiData.get(key));
            }

        /*会签思路：
        act_hi_identitylink记录着审批历史 ActivitiConstant.EXECUTOR_TYPE_p 标识审批通过
        1、节点设置中增加人数字段，表示需要多少人通过这个任务节点才通过
        2、此处查询审批历史，查看当前节点的审批情况，符合预设的人数调用 taskService.complete(id); 完成该节点任务
        否则只记录审批数据，不完成该任务节点
        3、会有的问题：
            1、如此，审批过的人代办中还会看到这条任务，需要标识自己审批过，但是这条任务自己不能再审了  或 能再审，但是再审记得把之前审批过的记录删掉
            2、下一个节点的审批人只能最后通过的人选择才有效
            3、如果下一个节点是会签，指定下一节点的审批人的数量必须不小于节点预设数量
            其他问题，待暴露
          */
            /*完成任务*/
            try {
                taskService.complete(ids);
            }catch (Exception e){
                throw new RuntimeException("流转条件不满足,请检查");
            }
            if(auditType.equals("back")){
                //驳回时,将流程历史中的delete_reason改成backed
                actZprocessService.updateTaskBack(ids);
            }
            if(auditType.equals("cancel")){
                //驳回时,将流程历史中的delete_reason改成backed
                actZprocessService.updateTaskCancel(ids);
            }
            ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey());
            //修改业务表的流程字段
            String actStatus = "1";
            if(auditType.equals("back")){
                actStatus = "3";
            }
            actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),actStatus);
            eaTask.setStatus(actStatus);

            task.getName();
            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
            // 判断下一个节点
            if(tasks!=null&&tasks.size()>0){
                for(Task t : tasks){
                    if(StrUtil.isBlank(assignees)){
                        // 如果下个节点未分配审批人为空 取消结束流程
                        List<LoginUser> users = actZprocessService.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId()).getUsers();
                        if(users==null||users.size()==0){
                            /*runtimeService.deleteProcessInstance(procInstId, "canceled-审批节点未分配审批人，流程自动中断取消");
                            actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED);
                            actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT);
                            actBusinessService.updateById(actBusiness);
                            //修改业务表的流程字段
                            actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"0");
                            eaTask.setStatus("0");

                            break;*/

                            throw new RuntimeException("下级节点未分配审批人，请设置");
                        }else{
                            // 避免重复添加
                            List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                            if(list==null||list.size()==0) {
                                // 分配了节点负责人分发给全部
                                for (LoginUser user : users) {
                                    taskService.addCandidateUser(t.getId(), user.getId());
                                    // 异步发消息
                                    actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);

                                    if(auditType.equals("back")){
                                        appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","3");
                                    }else if(auditType.equals("cancel")) {

                                    }else{
                                        appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                    }
                                }
                                taskService.setPriority(t.getId(), task.getPriority());
                            }
                        }
                    }else{
                        // 避免重复添加
                        List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                        if(list==null||list.size()==0) {

                            for(String assignee : assignees.split(",")){
                                taskService.addCandidateUser(t.getId(), assignee);
                                // 异步发消息
                                LoginUser user = sysBaseAPI.getUserById(assignee);
                                actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);
                                taskService.setPriority(t.getId(), 0);

                                if(auditType.equals("back")){
                                    appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","3");
                                }else if(auditType.equals("cancel")) {

                                }else{
                                    appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                }
                            }
                        }
                    }
                }
            } else {
                actBusiness.setStatus(ActivitiConstant.STATUS_FINISH);
                actBusiness.setResult(ActivitiConstant.RESULT_PASS);
                actBusinessService.updateById(actBusiness);
                // 异步发消息
                LoginUser user = sysBaseAPI.getUserById(actBusiness.getUserId());
                actZprocessService.sendMessage(actBusiness.getId(),loginUser,user,ActivitiConstant.MESSAGE_PASS_CONTENT,
                        String.format("您的 【%s】 申请已通过！",actBusiness.getTitle()),true, false, false);
                //修改业务表的流程字段
                actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"2");
                eaTask.setStatus("2");
                //判断是否变更单,变更单审核通过完结时,需要将变更单的信息更新到申请单
                updateApplyByAuditChange(actBusiness.getTableName(),actBusiness.getTableId());

                appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "审核已通过","已审核",eaTask.getFormId(),eaTask.getFormType(),"2","2");
            }
            // 记录实际审批人员
            if(auditType.equals("pass")){
                actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                        ActivitiConstant.EXECUTOR_TYPE_p, loginUser.getId(), ids, procInstId);
            }else{
                actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                        ActivitiConstant.EXECUTOR_TYPE_b, loginUser.getId(), ids, procInstId);
            }

            //更新任务
            if(tasks.size() > 0){
                eaTask.setWorkflowTaskId(tasks.get(0).getId());
            }
            eaTaskMapper.updateById(eaTask);

            //递归
            activitiVo.setAuditComment("同意");
            List<Task> tasks2 = taskService.createTaskQuery().processInstanceId(procInstId).list();
            for(Task t : tasks2){
                List<LoginUser> users = actZprocessService.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId()).getUsers();
                // 分配了节点负责人分发给全部
                for (LoginUser user : users) {
                    String realname = user.getRealname();

                    if(realname.equals(loginUser.getRealname()) && auditType.equals("pass")){
                        updateWrokflowByTaskId(activitiVo,"pass");
                    }
                }
            }
            return "";
        }
    }


    private void updateApplyByAuditChange(String tableName, String tableId) {
        if(tableName.equals("ea_entertain_change")){
            EaEntertainChange eaEntertainChange = eaEntertainChangeMapper.selectById(tableId);

            Map<String,Object> params = new HashMap<String,Object>();
            params.put("bill_no",eaEntertainChange.getApplyBillNo());
            List<EaEntertainApply> eaEntertainApplyList = eaEntertainApplyMapper.selectByMap(params);
            if(eaEntertainApplyList != null && eaEntertainApplyList.size() > 0){
                EaEntertainApply eaEntertainApply = eaEntertainApplyList.get(0);
                eaEntertainApply.setIsChanging("0");   //是否变更状态
                eaEntertainApply.setCostCompCodeId(eaEntertainChange.getCostCompCodeId());    //费用承担单位
                eaEntertainApply.setCostDept(eaEntertainChange.getCostDept());    //费用承担部门
                eaEntertainApply.setReceptionType(eaEntertainChange.getReceptionType());    //接待类型
                eaEntertainApply.setReceptionTime(eaEntertainChange.getReceptionTime());    //接待时间
                eaEntertainApply.setReceptionMan(eaEntertainChange.getReceptionMan());    //接待人数
                eaEntertainApply.setReceptionName(eaEntertainChange.getReceptionName());    //联系人姓名
                eaEntertainApply.setReceptionPhone(eaEntertainChange.getReceptionPhone());    //联系人电话
                eaEntertainApply.setCause(eaEntertainChange.getCause());    //事由
                eaEntertainApply.setAmount(eaEntertainChange.getAmount());     //申请金额
                eaEntertainApply.setVehicleArrangement(eaEntertainChange.getVehicleArrangement());    //用车安排
                eaEntertainApply.setAccommodationArrangements(eaEntertainChange.getAccommodationArrangements());    //住宿安排
                eaEntertainApply.setPresentSouvenirs(eaEntertainChange.getPresentSouvenirs());    //赠送纪念品
                eaEntertainApply.setMealArrangementDate(eaEntertainChange.getMealArrangementDate());    //用餐安排_时间
                eaEntertainApply.setMealArrangementAddr(eaEntertainChange.getMealArrangementAddr());    //用餐安排_地点
                eaEntertainApply.setMealArrangementStandard(eaEntertainChange.getMealArrangementStandard());    //用餐安排_标准
                eaEntertainApply.setMealArrangementMealAttendants(eaEntertainChange.getMealArrangementMealAttendants());    //用餐安排_陪餐人员
                eaEntertainApply.setMealArrangementWorkingPersonnel(eaEntertainChange.getMealArrangementWorkingPersonnel());    //用餐安排_工作人员
                eaEntertainApply.setIsOfficialReceptionsOther(eaEntertainChange.getIsOfficialReceptionsOther());    //公务接待是否协助安排其他用餐
                eaEntertainApply.setIsBusinessReceptionsOther(eaEntertainChange.getIsBusinessReceptionsOther());    //商务接待除宴请外是否安排工作餐
                eaEntertainApply.setBudgetExpensesSupplementaryNotes(eaEntertainChange.getBudgetExpensesSupplementaryNotes());    //预算费用补充说明

                //获取招待费变更单维护的明细数据
                //删除相应招待费维护的明细
                Map<String,Object> params3 = new HashMap<String,Object>();
                params3.put("entertain_apply_id",eaEntertainApply.getId());
                eaHostObjectMapper.deleteByMap(params3);
                //删除相应活动明细
                Map<String,Object> activitiParams = new HashMap<String,Object>();
                activitiParams.put("pid",eaEntertainApply.getId());
                eaEntertainReceptionActivityMapper.deleteByMap(activitiParams);

                Map<String,Object> params2 = new HashMap<String,Object>();
                params2.put("entertain_apply_id",eaEntertainChange.getId());
                List<EaHostObject> eaHostObjectList = eaHostObjectMapper.selectByMap(params2);
                if(eaHostObjectList != null && eaHostObjectList.size() > 0){
                    for (int i = 0; i < eaHostObjectList.size(); i++) {
                        EaHostObject eaHostObject = eaHostObjectList.get(i);
                        EaHostObject eaHostObject2 = new EaHostObject();
                        BeanUtils.copyProperties(eaHostObject,eaHostObject2);

                        //插入新的招待费明细
                        eaHostObject2.setId(Uuid32Util.getUUid());
                        eaHostObject2.setEntertainApplyId(eaEntertainApply.getId());
                        eaHostObjectMapper.insert(eaHostObject2);
                    }
                }
                Map<String,Object> params4 = new HashMap<String,Object>();
                params4.put("pid",eaEntertainChange.getId());
                List<EaEntertainReceptionActivity> eaEntertainReceptionActivities = eaEntertainReceptionActivityMapper.selectByMap(params4);
                if(eaEntertainReceptionActivities != null && eaEntertainReceptionActivities.size() > 0){
                    for (int i = 0; i < eaEntertainReceptionActivities.size(); i++) {
                        EaEntertainReceptionActivity eaEntertainReceptionActivity = eaEntertainReceptionActivities.get(i);
                        EaEntertainReceptionActivity eaEntertainReceptionActivity2 = new EaEntertainReceptionActivity();
                        BeanUtils.copyProperties(eaEntertainReceptionActivity,eaEntertainReceptionActivity2);

                        //插入新的活动明细
                        eaEntertainReceptionActivity2.setId(Uuid32Util.getUUid());
                        eaEntertainReceptionActivity2.setPid(eaEntertainApply.getId());
                        eaEntertainReceptionActivityMapper.insert(eaEntertainReceptionActivity2);
                    }
                }
                eaEntertainApplyMapper.updateById(eaEntertainApply);
            }
        }
        if(tableName.equals("ea_business_apply_change")){
            EaBusinessApplyChange eaBusinessApplyChange = eaBusinessApplyChangeMapper.selectById(tableId);

            Map<String,Object> params = new HashMap<String,Object>();
            params.put("bill_no",eaBusinessApplyChange.getEaBusinessApplyNo());
            List<EaBusinessApply> eaBusinessApplyList = eaBusinessApplyMapper.selectByMap(params);
            if(eaBusinessApplyList != null && eaBusinessApplyList.size() > 0){
                EaBusinessApply eaBusinessApply = eaBusinessApplyList.get(0);

                eaBusinessApply.setRegion(eaBusinessApplyChange.getRegion());    //目的地
                eaBusinessApply.setStartDate(eaBusinessApplyChange.getStartDate());    //开始时间
                eaBusinessApply.setEndDate(eaBusinessApplyChange.getEndDate());    //结束时间
                eaBusinessApply.setIfCompanyCar(eaBusinessApplyChange.getIsCompanyCar());    //是否公司配车
                eaBusinessApply.setPlateNumber(eaBusinessApplyChange.getPlateNumber());    //车牌号
                eaBusinessApply.setDriver(eaBusinessApplyChange.getDriver());    //司机
                eaBusinessApply.setCostCompCodeId(eaBusinessApplyChange.getCostCompCodeId());    //费用承担单位
                eaBusinessApply.setCostDept(eaBusinessApplyChange.getCostDept());    //费用承担部门
//                eaBusinessApply.setPersonnel(eaBusinessApplyChange.getPersonnel());    //出行人员
                eaBusinessApply.setExplainStr(eaBusinessApplyChange.getCause());    //事由
                eaBusinessApply.setCompanyCodeId(eaBusinessApplyChange.getCompanyCodeId());    //申请人单位
                eaBusinessApply.setDeptId(eaBusinessApplyChange.getDeptId());    //申请人部门
                eaBusinessApply.setType(eaBusinessApplyChange.getType());    //出差类型
                eaBusinessApply.setApplyMoney(eaBusinessApplyChange.getApplyMoney());    //申请金额
                eaBusinessApply.setTrafficTools(eaBusinessApplyChange.getTrafficTools());    //交通工具


                eaBusinessApplyMapper.updateById(eaBusinessApply);

                //删除出行人员明细
                Map<String,Object> personnelMap = new HashMap<String,Object>();
                personnelMap.put("ea_business_apply_id",eaBusinessApply.getId());
                eaBusinessPerDtlMapper.deleteByMap(personnelMap);

                Map<String,Object> params2 = new HashMap<String,Object>();
                params2.put("ea_business_apply_id",eaBusinessApplyChange.getId());
                List<EaBusinessPerDtl> eaBusinessPerDtlList = eaBusinessPerDtlMapper.selectByMap(params2);
                if(eaBusinessPerDtlList != null && eaBusinessPerDtlList.size() > 0){
                    for (int i = 0; i < eaBusinessPerDtlList.size(); i++) {
                        EaBusinessPerDtl eaBusinessPerDtl = eaBusinessPerDtlList.get(i);
                        EaBusinessPerDtl eaBusinessPerDtl2 = new EaBusinessPerDtl();
                        BeanUtils.copyProperties(eaBusinessPerDtl,eaBusinessPerDtl2);

                        //插入新的出差申请单明细
                        eaBusinessPerDtl2.setId(Uuid32Util.getUUid());
                        eaBusinessPerDtl2.setEaBusinessApplyId(eaBusinessApply.getId());
                        eaBusinessPerDtlMapper.insert(eaBusinessPerDtl2);
                    }
                }
            }
        }
    }

    @Transactional
    public String updateWrokflowByTaskId(EaTask eaTask) {
        String ids = eaTask.getWorkflowTaskId();     //工作流任务id
        String procInstId = eaTask.getProcinstId();     //流程id
        String assignees = "";    //下个节点审核人
        String comment = EmptyUtil.checkNull(eaTask.getMemo());
        if(ids.contains(",")){
            String[] id = ids.split(",");

            for (int i = 0; i < id.length; i++) {
                taskService.addComment(id[i], procInstId, comment);
                ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
                Task task = taskService.createTaskQuery().taskId(id[i]).singleResult();
                if(StrUtil.isNotBlank(task.getOwner())&&!("RESOLVED").equals(task.getDelegationState().toString())){
                    // 未解决的委托任务 先resolve
                    String oldAssignee = task.getAssignee();
                    taskService.resolveTask(id[i]);
                    taskService.setAssignee(id[i], oldAssignee);
                }

                /**
                 * 修改流程表单变量
                 * 表单参数
                 */
                LambdaQueryWrapper<ActBusiness> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ActBusiness::getProcInstId,pi.getProcessInstanceId());
                ActBusiness one = actBusinessService.getOne(queryWrapper);
                Map<String, Object> busiData = actBusinessService.getBusiData(one.getTableId(), one.getTableName());

                /**
                 * 获取所有流程变量 并修改
                 */
                for(String key : busiData.keySet()){
                    taskService.setVariable(id[i],key,busiData.get(key));
                }

        /*会签思路：
        act_hi_identitylink记录着审批历史 ActivitiConstant.EXECUTOR_TYPE_p 标识审批通过
        1、节点设置中增加人数字段，表示需要多少人通过这个任务节点才通过
        2、此处查询审批历史，查看当前节点的审批情况，符合预设的人数调用 taskService.complete(id); 完成该节点任务
        否则只记录审批数据，不完成该任务节点
        3、会有的问题：
            1、如此，审批过的人代办中还会看到这条任务，需要标识自己审批过，但是这条任务自己不能再审了  或 能再审，但是再审记得把之前审批过的记录删掉
            2、下一个节点的审批人只能最后通过的人选择才有效
            3、如果下一个节点是会签，指定下一节点的审批人的数量必须不小于节点预设数量
            其他问题，待暴露
          */
                /*完成任务*/
                try {
                    taskService.complete(id[i]);
                }catch (Exception e){
                    throw new RuntimeException("流转条件不满足,请检查");
                }
                ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey());
                //修改业务表的流程字段
                actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"1");
                eaTask.setStatus("1");

                task.getName();
                LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
                // 判断下一个节点
                if(tasks!=null&&tasks.size()>0){
                    for(Task t : tasks){
                        if(StrUtil.isBlank(assignees)){
                            // 如果下个节点未分配审批人为空 取消结束流程
                            List<LoginUser> users = actZprocessService.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId()).getUsers();
                            if(users==null||users.size()==0){
                                /*runtimeService.deleteProcessInstance(procInstId, "canceled-审批节点未分配审批人，流程自动中断取消");
                                actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED);
                                actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT);
                                actBusinessService.updateById(actBusiness);
                                //修改业务表的流程字段
                                actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"0");
                                eaTask.setStatus("0");

                                break;*/

                                throw new RuntimeException("下级节点未分配审批人，请设置");
                            }else{
                                // 避免重复添加
                                List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                                if(list==null||list.size()==0) {
                                    // 分配了节点负责人分发给全部
                                    for (LoginUser user : users) {
                                        taskService.addCandidateUser(t.getId(), user.getId());
                                        // 异步发消息
                                        actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);

                                        appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                    }
                                    taskService.setPriority(t.getId(), task.getPriority());
                                }
                            }
                        }else{
                            // 避免重复添加
                            List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                            if(list==null||list.size()==0) {

                                for(String assignee : assignees.split(",")){
                                    taskService.addCandidateUser(t.getId(), assignee);
                                    // 异步发消息
                                    LoginUser user = sysBaseAPI.getUserById(assignee);
                                    actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);
                                    taskService.setPriority(t.getId(), 0);

                                    appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                }
                            }
                        }
                    }
                } else {
                    actBusiness.setStatus(ActivitiConstant.STATUS_FINISH);
                    actBusiness.setResult(ActivitiConstant.RESULT_PASS);
                    actBusinessService.updateById(actBusiness);
                    // 异步发消息
                    LoginUser user = sysBaseAPI.getUserById(actBusiness.getUserId());
                    actZprocessService.sendMessage(actBusiness.getId(),loginUser,user,ActivitiConstant.MESSAGE_PASS_CONTENT,
                            String.format("您的 【%s】 申请已通过！",actBusiness.getTitle()),true, false, false);
                    //修改业务表的流程字段
                    actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"2");
                    eaTask.setStatus("2");

                    appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "审核已通过","已审核",eaTask.getFormId(),eaTask.getFormType(),"2","2");
                }
                // 记录实际审批人员
                actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                        ActivitiConstant.EXECUTOR_TYPE_p, loginUser.getId(), id[i], procInstId);

                //更新任务
                String workflowTaskId = "";
                for (int j = 0; j < tasks.size(); j++) {
                    if(workflowTaskId.equals("")){
                        workflowTaskId = tasks.get(j).getId();
                    }else{
                        workflowTaskId = workflowTaskId + "," + tasks.get(j).getId();
                    }
                }
                eaTask.setWorkflowTaskId(workflowTaskId);
                eaTaskMapper.updateById(eaTask);
            }
            return "";
        }else{
            taskService.addComment(ids, procInstId, comment);
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
            Task task = taskService.createTaskQuery().taskId(ids).singleResult();
            if(StrUtil.isNotBlank(task.getOwner())&&!("RESOLVED").equals(task.getDelegationState().toString())){
                // 未解决的委托任务 先resolve
                String oldAssignee = task.getAssignee();
                taskService.resolveTask(ids);
                taskService.setAssignee(ids, oldAssignee);
            }

            /**
             * 修改流程表单变量
             * 表单参数
             */
            LambdaQueryWrapper<ActBusiness> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ActBusiness::getProcInstId,pi.getProcessInstanceId());
            ActBusiness one = actBusinessService.getOne(queryWrapper);
            Map<String, Object> busiData = actBusinessService.getBusiData(one.getTableId(), one.getTableName());

            /**
             * 获取所有流程变量 并修改
             */
            for(String key : busiData.keySet()){
                taskService.setVariable(ids,key,busiData.get(key));
            }

        /*会签思路：
        act_hi_identitylink记录着审批历史 ActivitiConstant.EXECUTOR_TYPE_p 标识审批通过
        1、节点设置中增加人数字段，表示需要多少人通过这个任务节点才通过
        2、此处查询审批历史，查看当前节点的审批情况，符合预设的人数调用 taskService.complete(id); 完成该节点任务
        否则只记录审批数据，不完成该任务节点
        3、会有的问题：
            1、如此，审批过的人代办中还会看到这条任务，需要标识自己审批过，但是这条任务自己不能再审了  或 能再审，但是再审记得把之前审批过的记录删掉
            2、下一个节点的审批人只能最后通过的人选择才有效
            3、如果下一个节点是会签，指定下一节点的审批人的数量必须不小于节点预设数量
            其他问题，待暴露
          */
            /*完成任务*/
            try {
                taskService.complete(ids);
            }catch (Exception e){
                throw new RuntimeException("流转条件不满足,请检查");
            }
            ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey());
            //修改业务表的流程字段
            actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"1");
            eaTask.setStatus("1");

            task.getName();
            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
            // 判断下一个节点
            if(tasks!=null&&tasks.size()>0){
                for(Task t : tasks){
                    if(StrUtil.isBlank(assignees)){
                        // 如果下个节点未分配审批人为空 取消结束流程
                        List<LoginUser> users = actZprocessService.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId()).getUsers();
                        if(users==null||users.size()==0){
                            /*runtimeService.deleteProcessInstance(procInstId, "canceled-审批节点未分配审批人，流程自动中断取消");
                            actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED);
                            actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT);
                            actBusinessService.updateById(actBusiness);
                            //修改业务表的流程字段
                            actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"0");
                            eaTask.setStatus("0");

                            break;*/

                            throw new RuntimeException("下级节点未分配审批人，请设置");
                        }else{
                            // 避免重复添加
                            List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                            if(list==null||list.size()==0) {
                                // 分配了节点负责人分发给全部
                                for (LoginUser user : users) {
                                    taskService.addCandidateUser(t.getId(), user.getId());
                                    // 异步发消息
                                    actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);

                                    appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                                }
                                taskService.setPriority(t.getId(), task.getPriority());
                            }
                        }
                    }else{
                        // 避免重复添加
                        List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                        if(list==null||list.size()==0) {

                            for(String assignee : assignees.split(",")){
                                taskService.addCandidateUser(t.getId(), assignee);
                                // 异步发消息
                                LoginUser user = sysBaseAPI.getUserById(assignee);
                                actZprocessService.sendActMessage(loginUser,user,actBusiness,task.getName(),  true, false, false);
                                taskService.setPriority(t.getId(), 0);

                                appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "待处理","待处理",eaTask.getFormId(),eaTask.getFormType(),"1","1");
                            }
                        }
                    }
                }
            } else {
                actBusiness.setStatus(ActivitiConstant.STATUS_FINISH);
                actBusiness.setResult(ActivitiConstant.RESULT_PASS);
                actBusinessService.updateById(actBusiness);
                // 异步发消息
                LoginUser user = sysBaseAPI.getUserById(actBusiness.getUserId());
                actZprocessService.sendMessage(actBusiness.getId(),loginUser,user,ActivitiConstant.MESSAGE_PASS_CONTENT,
                        String.format("您的 【%s】 申请已通过！",actBusiness.getTitle()),true, false, false);
                //修改业务表的流程字段
                actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"2");
                eaTask.setStatus("2");

                appPush.pushMessage(user.getClientId(),"你有一条" + actBusiness.getTitle() + "审核已通过","已审核",eaTask.getFormId(),eaTask.getFormType(),"2","2");
            }
            // 记录实际审批人员
            actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                    ActivitiConstant.EXECUTOR_TYPE_p, loginUser.getId(), ids, procInstId);

            //更新任务
            if(tasks.size() > 0){
                eaTask.setWorkflowTaskId(tasks.get(0).getId());
            }
            eaTaskMapper.updateById(eaTask);

            //递归
            ActivitiVo activitiVo = new ActivitiVo();
            activitiVo.setAuditComment("同意");
            activitiVo.setId(eaTask.getFormId());
            activitiVo.setType(eaTask.getFormType());

            List<Task> tasks2 = taskService.createTaskQuery().processInstanceId(procInstId).list();
            for(Task t : tasks2){
                List<LoginUser> users = actZprocessService.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId()).getUsers();
                // 分配了节点负责人分发给全部
                for (LoginUser user : users) {
                    String realname = user.getRealname();

                    if(realname.equals(loginUser.getRealname())){
                        updateWrokflowByTaskId(activitiVo,"pass");
                    }
                }
            }
            return "";
        }
    }

    //审批到下一个节点
    @Override
    @Transactional
    public String pass(ActivitiVo activitiVo, EaTask eaTask) {
        taskService.setVariable(eaTask.getWorkflowTaskId(),"audit","1");
        //获取表名
        String tableName = changeTypeToTableName(eaTask.getFormType());
        //重新加载流程变量
        actZprocessService.reloadActivitiVariable(tableName,eaTask.getFormId(),eaTask.getWorkflowTaskId());

        //调用审核节点
        String auditType = "pass";
        updateWrokflowByTaskId(activitiVo,auditType);
        return "";
    }

    //通过判断单据的更新时间和当前传入的更新时间是否相同,返回提示
    @Override
    public String checkFormChange(String updateTime, String formType,String formId) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        String nowUpdateTime = "";   //单据的最新更新时间
        Map<String,Object> queryWrapper = new HashMap<String,Object>();
        queryWrapper.put("id",formId);  //单据id
        queryWrapper.put("page",0);
        queryWrapper.put("limit",0);

        switch (formType){
            case "1" :
//                EaTravel eaTravel = eaTravelMapper.selectById(formId);
                List<EaTravel> eaTravelList = eaTravelMapper.selectEaTravels(queryWrapper);
                if(eaTravelList.size() > 0){
                    nowUpdateTime = eaTravelList.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "2" :
//                EaLoanbill eaLoanbill = eaLoanbillMapper.selectById(formId);
                List<EaLoanbill> eaLoanbillList = eaLoanbillMapper.selectLoanBills(queryWrapper);
                if(eaLoanbillList.size() > 0){
                    nowUpdateTime = eaLoanbillList.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "3" :
//                EaRepaymentbill eaRepaymentbill = eaRepaymentbillMapper.selectById(formId);
                List<EaRepaymentbill> eaRepaymentbills = eaRepaymentbillMapper.selectRepaymentBills(queryWrapper);
                if(eaRepaymentbills.size() > 0){
                    nowUpdateTime = eaRepaymentbills.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "4" :
//                EaBusinessApply eaBusinessApply = eaBusinessApplyMapper.selectById(formId);
                List<EaBusinessApply> eaBusinessApplyList = eaBusinessApplyMapper.selectBusinessApplys(queryWrapper);
                if(eaBusinessApplyList.size() > 0){

                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "5" :
//                EaBusinessApplyChange eaBusinessApplyChange = eaBusinessApplyChangeMapper.selectById(formId);
                List<EaBusinessApplyChange> eaBusinessApplyChangeList = eaBusinessApplyChangeMapper.selectBusinessApplyChanges(queryWrapper);
                if(eaBusinessApplyChangeList.size() > 0){
                    nowUpdateTime = eaBusinessApplyChangeList.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "6" :
//                EaEntertainApply eaEntertainApply = eaEntertainApplyMapper.selectById(formId);
                List<EaEntertainApply> eaEntertainApplyList = eaEntertainApplyMapper.selectEntertainApplys(queryWrapper);
                if(eaEntertainApplyList.size() > 0){
                    nowUpdateTime = eaEntertainApplyList.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "7" :
//                EaEntertainChange eaEntertainChange = eaEntertainChangeMapper.selectById(formId);
                List<EaEntertainChange> eaEntertainChanges = eaEntertainChangeMapper.selectEntertainChanges(queryWrapper);
                if(eaEntertainChanges.size() > 0){
                    nowUpdateTime = eaEntertainChanges.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "8" :
//                EaEntertain eaEntertain = eaEntertainMapper.selectById(formId);
                List<EaEntertain> eaEntertainList = eaEntertainMapper.selecteaEntertains(queryWrapper);
                if(eaEntertainList.size() > 0){
                    nowUpdateTime = eaEntertainList.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "9" :
//                EaPayment eaPayment = eaPaymentMapper.selectById(formId);
                List<EaPayment> eaPayments = eaPaymentMapper.selectEaPayments(queryWrapper);
                if(eaPayments.size() > 0){
                    nowUpdateTime = eaPayments.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "10" :
//                EaCommunications eaCommunications = eaCommunicationsMapper.selectById(formId);
                List<EaCommunications> eaCommunications = eaCommunicationsMapper.selectEaCommunications(queryWrapper);
                if(eaCommunications.size() > 0){
                    nowUpdateTime = eaCommunications.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            case "11" :
//                EaPhoneRecord eaPhoneRecord = eaPhoneRecordMapper.selectById(formId);
                List<EaPhoneRecord> eaPhoneRecords = eaPhoneRecordMapper.selecteaPhoneRecord(queryWrapper);
                if(eaPhoneRecords.size() > 0){
                    nowUpdateTime = eaPhoneRecords.get(0).getTime();
                }
                if(nowUpdateTime.equals(updateTime)){
                    return "";
                }else{
                    return "单据状态已变更,请刷新";
                }
            default:
                return "";
        }
    }

    //驳回到发起人
    @Override
    @Transactional
    public String back(ActivitiVo activitiVo, EaTask eaTask) {
        taskService.setVariable(eaTask.getWorkflowTaskId(),"audit","2");  //驳回

        //调用审核节点
        String auditType = "back";
        updateWrokflowByTaskId(activitiVo,auditType);
        return "";
    }


    //撤销到上一级节点
    @Override
    @Transactional
    public String cancel(ActivitiCancelVo activitiCancelVo, EaTask eaTask) {
        String taskId = eaTask.getWorkflowTaskId();
        String procinstId = eaTask.getProcinstId();

        //获取已办任务里的最新的任务id(当前流程实例,同时end_time_不为空,task_id不为空) -- 当前已办人任务Id
        Map<String,Object> actHiTaskMap = actEaTaskMapper.selectLastHiTask(procinstId);
        String lastTaskId = ""; //最新的任务id
        if(actHiTaskMap != null){
            lastTaskId = EmptyUtil.checkNull(actHiTaskMap.get("ID_"));
        }

        //获取已办任务里特征表中的最新的数据:lastTaskId,procInstId
        String procInstId = eaTask.getProcinstId();
        List<Map<String, Object>> actHiIdentityList = actEaTaskMapper.selectLastHiIdentity(lastTaskId);

        //删除历史任务表任务(act_hi_taskinst)字段:id_(待办任务id)
        actEaTaskMapper.deleteHiTask(eaTask.getWorkflowTaskId());

        //更新历史任务表已办任务(act_hi_taskinst)字段:id_(已办任务id)::结束时间清空,持续时间清空,删除理由清空
        actEaTaskMapper.updateActHiTask(lastTaskId);

        //删除历史流程人员表-待办任务(act_hi_identitylink):task_id_(待办任务id)
        actEaTaskMapper.deleteActHiIdentityByTaskId(eaTask.getWorkflowTaskId());

        //删除历史流程人员表-已办任务(act_hi_identitylink):task_id_(已办任务id),流程实例id
        actEaTaskMapper.deleteActHiIdentity(lastTaskId,procInstId);

        //删除历史意见表-意见(act_hi_comment):task_id_(已办任务id)
        actEaTaskMapper.deleteActHiComment(lastTaskId);

        //删除运行时流程人员表-节点参与者(act_ru_identitylink):task_id_(待办任务id)
        actEaTaskMapper.deleteActRuIdentity(taskId);

        //删除运行时任务节点表-待办任务(act_ru_task)字段:id_(待办任务id)
        actEaTaskMapper.deleteRuTask(taskId);

        //将查询出来的已办任务(act_hi_taskinst)数据,插入到待办任务表(act_ru_task)
        actEaTaskMapper.insertActRuTask(actHiTaskMap);

        //将上一个节点已办的任务特征表(act_hi_identitylink),插入到待办的特征表(act_ru_identitylink)
        if(actHiIdentityList != null && actHiIdentityList.size() > 0){
            for (int i = 0; i < actHiIdentityList.size(); i++) {
                Map<String,Object> actHiIdentityMap = actHiIdentityList.get(i);
                actEaTaskMapper.insertActRuIdentity(actHiIdentityMap);
            }
        }

        // make

        //获取已办任务里的最新的任务id(再前一个已办任务id)(当前流程实例,同时end_time_不为空,task_id不为空)
        Map<String,Object> actHiTaskMap2 = actEaTaskMapper.selectLast2HiTask(procinstId,lastTaskId);
        String lastTaskId2 = ""; //最新的任务id(再前一个已办任务id)
        if(actHiTaskMap2 != null){
            lastTaskId2 = EmptyUtil.checkNull(actHiTaskMap2.get("ID_"));
        }

        // 这一步是否有必要？ 如果只是判断是否驳回，驳回都是在发起人节点，如果是发起人就可以设为3
        Map<String,Object> actHiActinst3 = actEaTaskMapper.selectActHiActinst(lastTaskId2);
        String deleteReason = "";           //节点操作状态:completed完成,backed驳回
        if(actHiActinst3 != null){
            deleteReason = EmptyUtil.checkNull(actHiActinst3.get("DELETE_REASON_"));
        }

        //获取已办任务里的最新的任务id(再前一个已办任务id)(当前流程实例,同时end_time_不为空,task_id不为空)
        Map<String,Object> actHiActinst = actEaTaskMapper.selectActHiActinst(lastTaskId);
        String startTime = "1900-01-01";    //开始时间
        if(actHiActinst != null){
            startTime = EmptyUtil.checkNull(actHiActinst.get("START_TIME_"));
        }

        //删除历史节点表(act_hi_actinst)中,字段:task_id_(已办任务id,并且时间大于上一个及诶单任务的所有记录)
        actEaTaskMapper.deleteActHiActinst(startTime);

        //更新历史节点表(act_hi_actinst)中,字段:task_id_(已办任务id),将结束日期清空,持续时间清空
        actEaTaskMapper.updateActHiActinst(lastTaskId);

        //更新运行时流程执行实例表(act_ru_execution)字段:act_id_为上一节点任务的task_def_key_值
        String taskDefKey = EmptyUtil.checkNull(actHiTaskMap.get("TASK_DEF_KEY_"));
        actEaTaskMapper.updateActRuExecution(procinstId,taskDefKey);

        //查询单据的表名称,用于更新单据状态
        String tableName = changeTypeToTableName(eaTask.getFormType());

        //更新任务表(ea_task)的当前任务id为最新的任务id
        eaTask.setWorkflowTaskId(lastTaskId);
        //更新单据的状态,0初始状态,1审批中,3已驳回
        if(deleteReason.equals("backed")){
            eaTask.setStatus("3");
            //更新单据状态
            actBusinessService.updateBusinessStatus(tableName, eaTask.getFormId(),"3");
        }else{
            //查询已办任务总条数(act_hi_taskinst),如果条数是1,就说明是初始状态
            int count = actEaTaskMapper.selectActHiActinstCount(procinstId);
            if(count == 1){
                eaTask.setStatus("0");
                //更新单据状态
                actBusinessService.updateBusinessStatus(tableName, eaTask.getFormId(),"0");
            }else{
                eaTask.setStatus("1");
                //更新单据状态
                actBusinessService.updateBusinessStatus(tableName, eaTask.getFormId(),"1");
            }
        }
        eaTaskMapper.updateById(eaTask);
        return "";
    }

    //根据已办任务Id确定是否当前任务是否可以被撤回
    @Override
    public int getTaskIsCancel(ActivitiCancelVo activitiCancelVo) {
        //eaTask,单据涉及到的表名(如差旅费报销单ea_travel)
        Map<String,Object> taskParams = new HashMap<String,Object>();
        taskParams.put("form_id",activitiCancelVo.getId());
        List<EaTask> eaTaskList  = eaTaskMapper.selectByMap(taskParams);
        EaTask eaTask = new EaTask();
        if(eaTaskList.size() > 0){
            eaTask = eaTaskList.get(0);
        }

        String status = EmptyUtil.checkNull(eaTask.getStatus());   //状态
        if(status.equals("2")){  //已审批
            return 0;
        }

        //判断单据是否已经被变更
        /*String updateTime = EmptyUtil.checkNull(activitiCancelVo.getUpdateTime());   //更新时间
        String msg = checkFormChange(updateTime,eaTask.getFormType(),eaTask.getFormId());
        if(!msg.equals("")){
            return 0;
        }else{

        }*/
        String taskId2 = EmptyUtil.checkNull(activitiCancelVo.getTaskId());    //已办任务id
        Map<String,Object> actHiActinst2 = actEaTaskMapper.selectActHiActinst(taskId2);
        String startTime2 = "";
        String procInstId2 = "";
        if(actHiActinst2 == null){
            return 0;
        }else{
            startTime2 = EmptyUtil.checkNull(actHiActinst2.get("START_TIME_"));   //开始时间
            procInstId2 = EmptyUtil.checkNull(actHiActinst2.get("PROC_INST_ID_"));   //流程id
        }

        List<Map<String,Object>> actHiTaskList2 = actEaTaskMapper.selectActHiTaskFromTime(startTime2,procInstId2);
        if(actHiTaskList2 == null || actHiTaskList2.size() == 0  || actHiTaskList2.size() > 1){
            return 0;
        }else{
            return 1;
        }
    }

    //根据单据id查询最近一个已办任务id
    @Override
    public String getLastHiTaskId(IdVo idVo) {
        //eaTask,单据涉及到的表名(如差旅费报销单ea_travel)
        Map<String,Object> taskParams = new HashMap<String,Object>();
        taskParams.put("form_id",idVo.getId());
        List<EaTask> eaTaskList  = eaTaskMapper.selectByMap(taskParams);
        EaTask eaTask = new EaTask();
        if(eaTaskList.size() > 0){
            eaTask = eaTaskList.get(0);
        }

        String taskId = eaTask.getWorkflowTaskId();
        String procinstId = eaTask.getProcinstId();

        //获取指定任务的开始时间
        Map<String,Object> actHiActinst = actEaTaskMapper.selectActHiActinst(taskId);
        String startTime = EmptyUtil.checkNull(actHiActinst.get("START_TIME_"));   //开始时间

        List<Map<String,Object>> actHiTaskList2 = actEaTaskMapper.selectActHiTaskFromTime2(startTime,procinstId);
        if(actHiTaskList2 == null || actHiTaskList2.size() == 0){
            return "";
        }else{
            String lastTaskId = EmptyUtil.checkNull(actHiTaskList2.get(0).get("ID_"));    //最新的任务id
            return lastTaskId;
        }
    }
}
